package cn.walls1717.juc.future;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 线程池选用相关测试
 *
 * @author walls1717
 * @create 2022/12/09 16:41
 **/
@Slf4j
public class CompletableFutureWithThreadPoolDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        /*
         * 情况1：
         *   如果supplyAsync()没有指定线程池，后面后的是thenRun()，那么所有的都会使用默认线程池。
         * 情况2：
         *   如果supplyAsync()指定线程池，后面使用的是thenRun()，那么所有的都会使用线程池线程。
         *   还有一种特殊情况是supplyAsync()的执行速度非常快，那么thenRun()也不会使用线程池线程，直接使用main线程执行了。
         * 情况3：
         *   如果supplyAsync()指定线程池，后面使用的是thenRunAsync()，那么只有supplyAsync()方法使用线程池线程。其它还是默认线程。
         */
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread().getName() + "线程开始执行...");
            /*try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            return "start";
        }, executor).thenRun(() -> {
            log.info(Thread.currentThread().getName() + "线程开始执行...");
            try {
                TimeUnit.MILLISECONDS.sleep(13);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).thenRun(() -> {
            log.info(Thread.currentThread().getName() + "线程开始执行...");
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).thenRun(() -> {
            log.info(Thread.currentThread().getName() + "线程开始执行...");
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).thenRun(() -> {
            log.info(Thread.currentThread().getName() + "线程开始执行...");
            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        log.info(String.valueOf(future.get(2L, TimeUnit.SECONDS)));

        executor.shutdown();
    }
}
